using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using BanZuiCloudControlAgent.Core.Mqtt.Enum;
using BanZuiCloudControlAgent.Core.Mqtt.Listener;
using BanZuiCloudControlAgent.Core.Mqtt.Models;
using BanZuiCloudControlAgent.Core.Mqtt.Sender;
using BanZuiCloudControlAgent.Core.Tasks.Queue;
using BanZuiCloudControlAgent.Utils.Common;
using BanZuiCloudControlAgent.Utils.Exceptions;
using BanZuiCloudControlAgent.Utils.Logging;

namespace BanZuiCloudControlAgent.Core.Mqtt
{
    /// <summary>
    /// MQTT服务，提供MQTT连接管理、消息发送和接收功能
    /// </summary>
    public class MqttService : IDisposable
    {
        private readonly NLog.Logger _logger = NLog.LogManager.GetCurrentClassLogger();
        private readonly MqttClientManager _clientManager;
        private readonly MqttMessageSender _messageSender;
        private readonly MqttMessageHandler _messageHandler;
        private readonly MqttMessageListener _messageListener;
        private readonly MqttTopics _mqttTopics;
        private readonly Timer _heartbeatTimer;
        private bool _isRunning;
        private int _heartbeatInterval;
        private bool _disposed;
        
        /// <summary>
        /// 任务队列，用于获取任务状态
        /// </summary>
        private TaskQueue _taskQueue;

        /// <summary>
        /// 任务接收事件
        /// </summary>
        public event EventHandler<TaskDispatchEventArgs> TaskReceived
        {
            add { _messageHandler.TaskReceived += value; }
            remove { _messageHandler.TaskReceived -= value; }
        }

        /// <summary>
        /// 配置接收事件
        /// </summary>
        public event EventHandler<ConfigEventArgs> ConfigReceived
        {
            add { _messageHandler.ConfigReceived += value; }
            remove { _messageHandler.ConfigReceived -= value; }
        }

        /// <summary>
        /// 更新任务接收事件
        /// </summary>
        public event EventHandler<UpdateTaskEventArgs> UpdateTaskReceived
        {
            add { _messageHandler.UpdateTaskReceived += value; }
            remove { _messageHandler.UpdateTaskReceived -= value; }
        }

        /// <summary>
        /// 连接状态变更事件
        /// </summary>
        public event EventHandler<MqttConnectionStatusChangedEventArgs> ConnectionStatusChanged
        {
            add { _clientManager.ConnectionStatusChanged += value; }
            remove { _clientManager.ConnectionStatusChanged -= value; }
        }

        /// <summary>
        /// 是否已连接到MQTT服务器
        /// </summary>
        public bool IsConnected => _clientManager.IsConnected;

        /// <summary>
        /// 获取消息发送器
        /// </summary>
        /// <returns>消息发送器</returns>
        public MqttMessageSender GetMessageSender()
        {
            return _messageSender;
        }
        
        /// <summary>
        /// 设置任务队列
        /// </summary>
        /// <param name="taskQueue">任务队列</param>
        public void SetTaskQueue(TaskQueue taskQueue)
        {
            _taskQueue = taskQueue;
            _logger.Info("已设置任务队列");
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        public MqttService()
        {
            try
            {
                _logger.Info("初始化MQTT服务");

                // 加载配置
                var options = MqttClientOptions.FromConfig();
                _heartbeatInterval = options.KeepAliveInterval;

                // 创建MQTT主题
                _mqttTopics = new MqttTopics(options.TopicPrefix, options.DeviceCode);

                // 创建MQTT客户端管理器
                _clientManager = new MqttClientManager(options);

                // 创建消息处理器
                _messageHandler = new MqttMessageHandler(_mqttTopics);

                // 创建消息监听器
                _messageListener = new MqttMessageListener(_clientManager, _messageHandler);

                // 创建消息发送器
                _messageSender = new MqttMessageSender(_clientManager, _mqttTopics);

                // 创建心跳定时器
                _heartbeatTimer = new Timer(SendHeartbeat, null, Timeout.Infinite, Timeout.Infinite);

                _isRunning = false;
                _disposed = false;

                _logger.Info("MQTT服务初始化完成");
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "初始化MQTT服务失败");
                throw;
            }
        }

        /// <summary>
        /// 启动MQTT服务
        /// </summary>
        public async Task StartAsync()
        {
            try
            {
                if (_isRunning)
                {
                    _logger.Warn("MQTT服务已经在运行中");
                    return;
                }

                _logger.Info("启动MQTT服务");

                // 获取最新配置
                var options = MqttClientOptions.FromConfig();
                _heartbeatInterval = options.KeepAliveInterval;

                // 更新MQTT客户端选项
                _clientManager.UpdateOptions(options);

                try
                {
                    // 初始化MQTT客户端
                    await _clientManager.InitializeAsync();

                    // 连接到MQTT服务器
                    await _clientManager.ConnectAsync();

                    // 连接后检查状态
                    _logger.Debug($"MQTT客户端连接后状态: IsConnected={_clientManager.IsConnected}");
                }
                catch (InvalidOperationException ex) when (ex.Message.Contains("already started"))
                {
                    _logger.Warn("MQTT客户端已经启动，继续执行后续步骤");
                    _logger.Debug($"MQTT客户端已启动状态: IsConnected={_clientManager.IsConnected}");
                }

                // 启动消息监听器
                _messageListener.Start();

                // 启动心跳定时器
                StartHeartbeatTimer();

                _isRunning = true;
                _logger.Info("MQTT服务启动成功");
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "启动MQTT服务失败");
                throw;
            }
        }

        /// <summary>
        /// 停止MQTT服务
        /// </summary>
        /// <param name="isCancelReconnect">是否是取消重连</param>
        /// <param name="isClosing">是否在应用程序关闭过程中</param>
        public async Task StopAsync(bool isCancelReconnect = false, bool isClosing = false)
        {
            try
            {
                if (!_isRunning)
                {
                    _logger.Warn("MQTT服务未在运行");
                    return;
                }

                if (isCancelReconnect)
                {
                    _logger.Info("取消MQTT重连");
                }
                else
                {
                    _logger.Info("停止MQTT服务");
                }

                // 停止心跳定时器
                StopHeartbeatTimer();

                try
                {
                    // 发送断开连接消息
                    if (_clientManager.IsConnected && !isCancelReconnect && !isClosing)
                    {
                        await _messageSender.SendDisconnectMessageAsync("normal_disconnect");
                    }
                }
                catch (Exception ex)
                {
                    _logger.Warn($"发送断开连接消息失败: {ex.Message}");
                }

                // 停止消息监听器
                _messageListener.Stop();

                try
                {
                    // 断开MQTT连接
                    await _clientManager.DisconnectAsync(isCancelReconnect, isClosing);
                }
                catch (Exception ex)
                {
                    if (isCancelReconnect)
                    {
                        _logger.Warn($"取消重连失败: {ex.Message}");
                    }
                    else
                    {
                        _logger.Warn($"断开MQTT连接失败: {ex.Message}");
                    }
                }

                _isRunning = false;

                if (isCancelReconnect)
                {
                    _logger.Info("已取消MQTT重连");
                }
                else
                {
                    _logger.Info("MQTT服务已停止");
                }
            }
            catch (Exception ex)
            {
                if (isCancelReconnect)
                {
                    _logger.Error(ex, "取消MQTT重连失败");
                }
                else
                {
                    _logger.Error(ex, "停止MQTT服务失败");
                }
                throw;
            }
        }


        /// <summary>
        /// 启动心跳定时器
        /// </summary>
        private void StartHeartbeatTimer()
        {
            try
            {
                _logger.Debug($"启动心跳定时器，间隔: {_heartbeatInterval}秒");
                _heartbeatTimer.Change(TimeSpan.Zero, TimeSpan.FromSeconds(_heartbeatInterval));
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "启动心跳定时器失败");
            }
        }

        /// <summary>
        /// 停止心跳定时器
        /// </summary>
        private void StopHeartbeatTimer()
        {
            try
            {
                _logger.Debug("停止心跳定时器");
                _heartbeatTimer.Change(Timeout.Infinite, Timeout.Infinite);
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "停止心跳定时器失败");
            }
        }

        /// <summary>
        /// 发送状态上报消息
        /// </summary>
        /// <param name="isHeartbeat">是否为心跳消息</param>
        /// <param name="isFirstConnect">是否为首次连接</param>
        /// <returns>发送结果</returns>
        public async Task<bool> SendStatusReportAsync(bool isHeartbeat = true, bool isFirstConnect = false)
        {
            return await _messageSender.SendStatusReportAsync(isHeartbeat, isFirstConnect, _taskQueue);
        }

        /// <summary>
        /// 发送心跳
        /// </summary>
        /// <param name="state">状态对象</param>
        private async void SendHeartbeat(object state)
        {
            try
            {
                if (_isRunning && _clientManager.IsConnected)
                {
                    _logger.Debug("发送心跳");
                    bool success = await _messageSender.SendStatusReportAsync(true, false, _taskQueue);

                    if (!success)
                    {
                        _logger.Warn("心跳发送失败，检查连接状态");
                        await CheckConnectionStatusAsync();
                    }
                }
                else if (_isRunning && !_clientManager.IsConnected)
                {
                    // 如果服务在运行但客户端未连接，尝试重新连接
                    _logger.Warn("心跳检测到客户端未连接，尝试重新连接");
                    await CheckConnectionStatusAsync();
                }
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "发送心跳失败");
                // 心跳发送异常，检查连接状态
                await CheckConnectionStatusAsync();
            }
        }

        /// <summary>
        /// 检查连接状态，如果未连接则尝试重新连接
        /// </summary>
        private async Task CheckConnectionStatusAsync()
        {
            try
            {
                if (!_clientManager.IsConnected && _isRunning)
                {
                    _logger.Info("检测到连接断开，尝试重新连接");

                    // 停止心跳定时器，避免重复触发
                    StopHeartbeatTimer();

                    try
                    {
                        // 尝试重新连接
                        await _clientManager.ConnectAsync();

                        // 如果连接成功，重新启动心跳定时器
                        if (_clientManager.IsConnected)
                        {
                            _logger.Info("重新连接成功，重新启动心跳定时器");
                            StartHeartbeatTimer();
                        }
                        else
                        {
                            _logger.Warn("重新连接失败，等待自动重连机制");
                            // 延迟一段时间后重新启动心跳定时器
                            await Task.Delay(TimeSpan.FromSeconds(_heartbeatInterval));
                            StartHeartbeatTimer();
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger.Error(ex, "重新连接失败");
                        // 延迟一段时间后重新启动心跳定时器
                        await Task.Delay(TimeSpan.FromSeconds(_heartbeatInterval));
                        StartHeartbeatTimer();
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "检查连接状态失败");
                // 确保心跳定时器重新启动
                StartHeartbeatTimer();
            }
        }

        /// <summary>
        /// 更新心跳间隔
        /// </summary>
        /// <param name="interval">新的心跳间隔（秒）</param>
        public void UpdateHeartbeatInterval(int interval)
        {
            try
            {
                if (interval <= 0)
                {
                    _logger.Warn($"无效的心跳间隔: {interval}秒，使用默认值");
                    interval = 30; // 使用默认值
                }

                _heartbeatInterval = interval;
                _logger.Info($"更新心跳间隔为: {interval}秒");

                if (_isRunning)
                {
                    // 重新启动心跳定时器
                    _heartbeatTimer.Change(TimeSpan.Zero, TimeSpan.FromSeconds(_heartbeatInterval));
                }
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "更新心跳间隔失败");
            }
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        /// <param name="disposing">是否正在释放托管资源</param>
        protected virtual void Dispose(bool disposing)
        {
            if (_disposed)
                return;

            if (disposing)
            {
                try
                {
                    // 停止MQTT服务
                    if (_isRunning)
                    {
                        StopAsync().Wait();
                    }

                    // 释放心跳定时器
                    _heartbeatTimer?.Dispose();

                    // 释放MQTT客户端管理器
                    _clientManager?.Dispose();
                }
                catch (Exception ex)
                {
                    _logger.Error(ex, "释放MQTT服务资源失败");
                }
            }

            _disposed = true;
        }
    }
}